package iofunc

import (
	//"io"
	"os"
	"fmt"
	"errors"
	"crypto/rand"
)

func genRandStr(lenBytes int) (string, error) {
	var (
		tmpBytes []byte = make([]byte, lenBytes)
		err error
		i int
	)
	// Init byte array with random bytes.
	_, err = rand.Read(tmpBytes)
	if err != nil {
		return "", err
	}

	for i = 0; i < len(tmpBytes); i = i + 1 {
		tmpBytes[i] = tmpBytes[i] % 62
		if tmpBytes[i] < 10 {
			tmpBytes[i] = tmpBytes[i] + '0'
		} else if tmpBytes[i] < 36 {
			tmpBytes[i] = tmpBytes[i] - 10 + 'a'
		} else {
			tmpBytes[i] = tmpBytes[i] - 36 + 'A'
		}
	}
	return string(tmpBytes), nil
}

// A little unit of file test. Just write a file with random bytes.
// It should return status.
func RandWrite(subDir *SubDir, buf []byte, wLen int) error {
	const (
		lenFileName int = 16
	)
	var (
		filename string = ""
		file *os.File
		err error
	)

	// Get file name.
	filename, err = genRandStr(lenFileName)
	if err != nil {
		fmt.Println("ERROR: ", err)	// DEBUG
		return err
	}
	filename = subDir.Name + "/" + filename
	// If exist, skip.
	if subDir.Entry[filename] != 0 {
		err = errors.New("SKIP: skip write")
		return err
	}

	// Open and write file.
	file, err = os.Create(filename)
	if err != nil {
		//fmt.Println("ERROR: ", err)	// DEBUG
		return err
	}
	file.Write(buf[:wLen])
	subDir.Entry[filename] = wLen

	return nil
}

// A little unit of file test. Just read a file.
// If it do some check sum, it will be better.
// It should return status.
func RandRead(subDir *SubDir, maxSize int) error {
	var (
		filename string
		file *os.File
		fileLen int
		buf []byte
		readLen int
		err error
	)

	buf = make([]byte, maxSize)
	loopindex:
	for filename, fileLen = range subDir.Entry {
		file, err = os.Open(filename)
		if err != nil {
			//fmt.Println("ERROR: ", err)
			return err
		} else if fileLen == 0 {
			continue
		}
		readLen, err = file.Read(buf)
		if err != nil {
			//fmt.Println("ERROR: ", err)
			return err
		} else if readLen != fileLen {
			err = errors.New("ERROR: file not matched.")
			// DEBUG
			return err
		}
		err = file.Close()
		if err != nil {
			//fmt.Println("ERROR: ", err)
			return err
		}
		break loopindex
	}
	if fileLen == 0 {
		err = errors.New("SKIP: no file.")
		return err
	}
	return nil
}

// A little unit of file test. Just delete a file.
// It should return status.
func RandDelete(subDir *SubDir) error {
	var (
		filename string
		fileLen int
		err error
	)

	loopindex:
	for filename, fileLen = range subDir.Entry {
		err = os.Remove(filename)
		if err != nil {
			fmt.Println("ERROR: ", err)
			return err
		} else {
			delete(subDir.Entry, filename)
			break loopindex
		}
	}
	if fileLen == 0 {
		err = errors.New("SKIP: no file.")
		return err
	}
	return nil
}

